package com.xiebishe.mylibrary.common.mvvm;

import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.lifecycle.GenericLifecycleObserver;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.Observer;

import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author xxZhu
 * @class EventLiveData
 * @describe 时间发送型 的LiveData
 * <p>
 * 1.激活状态为create-->destroy
 * 2.unActive-->active 时不会发送历史最新数据
 */
public class EventLiveData<T> extends DefaultLiveData<T> {

    private LinkedHashMap<Observer<? super T>, ObserverWrapper> map = new LinkedHashMap<>();

    @Override
    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        ObserverWrapper previous = map.get(observer);
        if (previous != null) {
            if (previous.owner != owner)
                throw new IllegalArgumentException("observer cannot observe for different owner");

            return;
        }

        ObserverWrapper observerWrapper = new ObserverWrapper(owner, observer);
        map.put(observer, observerWrapper);
        owner.getLifecycle().addObserver(observerWrapper);
        super.observeForever(observerWrapper);
        observerWrapper.initialized = true;
    }

    @Override
    @MainThread
    public void removeObserver(@NonNull Observer<? super T> observer) {
        ObserverWrapper observerWrapper = map.remove(observer);
        if (observerWrapper != null) {
            super.removeObserver(observerWrapper);
        } else {
            super.removeObserver(observer);
        }
    }

    @Override
    @MainThread
    public void removeObservers(@NonNull LifecycleOwner owner) {
        Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Observer<? super T>, ObserverWrapper> entry = iterator.next();
            if (entry.getValue().owner == owner) {
                super.removeObserver(entry.getValue());
                iterator.remove();
            }
        }
    }

    @Override
    @MainThread
    public void observeForever(@NonNull Observer<? super T> observer) {
        ObserverWrapper previous = map.get(observer);
        if (previous != null) {
            throw new IllegalArgumentException("observer cannot observe for different owner");
        }
        super.observeForever(observer);
    }

    private class ObserverWrapper implements Observer<T>, GenericLifecycleObserver {
        private final Observer<? super T> origin;
        private final LifecycleOwner owner;
        boolean initialized;

        ObserverWrapper(LifecycleOwner owner, Observer<? super T> origin) {
            this.owner = owner;
            this.origin = origin;
        }

        @Override
        public void onChanged(T t) {
            if (initialized) {
                origin.onChanged(t);
            }
        }

        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            if (source.getLifecycle().getCurrentState() == Lifecycle.State.DESTROYED) {
                removeObserver(origin);
            }
        }
    }
}
